package anonymous;

import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;

import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.messages.Command;
import rescuecore2.log.Logger;

import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import rescuecore2.standard.entities.AmbulanceTeam;
import rescuecore2.standard.entities.Human;
import rescuecore2.standard.entities.Civilian;
import rescuecore2.standard.entities.Refuge;

/**
  A sample ambulance team agent.
  */
public class AnonymousAmbulanceTeam extends AbstractAnonymousAgent<AmbulanceTeam> {
	private Collection<EntityID> unexploredBuildings;

	@Override
		protected boolean iAmAmbulance(){
			return true;
		}

	@Override
		public String toString() {
			return "Anonymous ambulance team";
		}

	@Override
		protected void postConnect() {
			super.postConnect();
			model.indexClass(StandardEntityURN.CIVILIAN, StandardEntityURN.FIRE_BRIGADE, StandardEntityURN.POLICE_FORCE, StandardEntityURN.AMBULANCE_TEAM, StandardEntityURN.REFUGE, StandardEntityURN.BUILDING);
			unexploredBuildings = new HashSet<EntityID>(buildingIDs);
		}
	@Override
	protected void startup(int time){
		//TODO: Startup
	};
	@Override
	protected void patrol(int time){
		//TODO: Improve patrol
		if(this.hasTask()){
			this.current_state = State.TASK;
			task(time);
		}
		else{
			List<EntityID> path = randomWalk();
			sendMove(time, path);
		}
	}
	@Override
	protected void task(int time){
		if(!this.hasTask()){
			this.current_state = State.PATROL;
			patrol(time);
		}
		else{
			Task current_task = taskList.top(model);
			if(someoneOnBoard()){
				//someone on board
				if(location()instanceof Refuge){
					//at refuge
					Logger.debug("TANNOS - Amb Largou"+ current_task.eID);
					sendUnload(time);
				}
				else{
					List<EntityID> path = search.breadthFirstSearch(me().getPosition(), refugeIDs);
					if (path != null) {
						//go to refuge
						Logger.debug("TANNOS - MOVING_A");
						sendMove(time, path);
					}
					else{
						//TODO: call for help to unblock something
						Logger.debug("TANNOS - BLOCKED_A");
					}
				}
			}
			else{
				//going to get someone
				if( current_task.location == location().getLocation(model) ){
					//already in the right place
					Logger.debug("TANNOS - Amb Pegou"+ current_task.eID);
					sendLoad(time, current_task.eID);
				}
				else{
					//going to take it
					List<EntityID> path = search.breadthFirstSearch(me().getPosition(), current_task.eID);
					if (path != null) {
						Logger.debug("TANNOS - MOVING_B");
						sendMove(time, path);
					}
					else{
						//TODO: call for help to unblock something
						Logger.debug("TANNOS - BLOCKED_B");              // << SEMPRE CAI AQUI
					}
				}
			}
		}
	}
	@Override
	protected void displacement(int time){
		//TODO: displacement
	}

	@Override
		protected EnumSet<StandardEntityURN> getRequestedEntityURNsEnum() {
			return EnumSet.of(StandardEntityURN.AMBULANCE_TEAM);
		}

	private boolean someoneOnBoard() {
		for (StandardEntity next : model.getEntitiesOfType(StandardEntityURN.CIVILIAN)) {
			if (((Human)next).getPosition().equals(getID())) {
				Logger.debug(next + " is on board");
				return true;
			}
		}
		return false;
	}

	private List<Human> getTargets() {
		List<Human> targets = new ArrayList<Human>();
		for (StandardEntity next : model.getEntitiesOfType(StandardEntityURN.CIVILIAN, StandardEntityURN.FIRE_BRIGADE, StandardEntityURN.POLICE_FORCE, StandardEntityURN.AMBULANCE_TEAM)) {
			Human h = (Human)next;
			if (h == me()) {
				continue;
			}
			if (h.isHPDefined()
					&& h.isBuriednessDefined()
					&& h.isDamageDefined()
					&& h.isPositionDefined()
					&& h.getHP() > 0
					&& (h.getBuriedness() > 0 || h.getDamage() > 0)) {
				targets.add(h);
					}
		}
		Collections.sort(targets, new DistanceSorter(location(), model));
		return targets;
	}

	private void updateUnexploredBuildings(ChangeSet changed) {
		for (EntityID next : changed.getChangedEntities()) {
			unexploredBuildings.remove(next);
		}
	}
}
